
import 'package:get/get.dart';
import 'package:xreader/common/app_config.dart';
import 'package:xreader/common/dxm_utils.dart';
import 'package:xreader/common/http_common.dart';
import 'package:xreader/db/provider/t_book_cont_provider.dart';
import 'package:xreader/db/provider/t_book_provider.dart';
import 'package:xreader/db/provider/t_sys_provider.dart';
import 'package:xreader/dto/app_config_vo_entity.dart';
import 'package:xreader/dto/book_local_page_vo_entity.dart';
import 'package:xreader/logs/log.dart';
import 'package:xreader/model/t_book_cont_entity.dart';
import 'package:xreader/model/t_book_entity.dart';
import 'package:xreader/model/t_sys_entity.dart';
import 'package:xreader/params/book_cont_params.dart';
import 'package:xreader/params/book_params.dart';
import 'package:xreader/vo/page_info.dart';

class BookService {
  /// 远程同步，数据增量
  /// 上下架书籍
  static initLocalBookInfo(AppConfigVoEntity? appConfig) async{
      if(appConfig == null){
          return;
      }
      TBookProvider tBookProvider = Get.find();
      TSysProvider tSysProvider = Get.find();
      String remoteUpdateSign = appConfig.updateSign ?? "";
      //判断是否需要同步 根据updateSign 判断
      bool needSync = await tSysProvider.checkNeedSync(remoteUpdateSign);
      //获取本地全部数据
      List<TBookEntity> dbBooks = await tBookProvider.getAllBaseData();
      Map<int,int> dbBorderMap = {};
      Map<int,String> dbBsignMap = {};
      dbBooks.forEach((dbRecord) {
        int id = dbRecord.id ?? -1;
        dbBorderMap[id] = dbRecord.border ?? -1;
        dbBsignMap[id] = dbRecord.bsign ?? "";
      });
      Log.i("是否需要同步 needSync=$needSync");
      if(needSync){
        //同步远程
        int totalPage = appConfig.totalPage ?? 0;
        bool hasErr = false;
        //分页获取
        for(int page=totalPage;page>0 && needSync ;page--){
          //远程接口
          String api = AppConfig.bookAppLocalPageApi(page);
          //远程数据接口
          try{
            List<TBookEntity> updateDatas = [];
            BookLocalPageVoEntity localPageData = await HttpCommmon.getLocalAppBookPage(api);
            List<TBookEntity> remoteDatas = localPageData.datas ?? [];
            for(TBookEntity remoteData in remoteDatas){
              int remoteId = remoteData.id ?? 0;
              String remoteBsign = remoteData.bsign ?? "";
              String dbBsign = dbBsignMap[remoteId] ?? "";
              if(remoteBsign.isNotEmpty && remoteBsign.compareTo(dbBsign) != 0){
                //需要更新 remoteData 到本地db
                updateDatas.add(remoteData);
              }
            }
            //同步更新到db
            await tBookProvider.insertOrUpdateBatch(updateDatas);
            //判断有无必要继续请求远程
            String dbUpdateSign = await tBookProvider.getAllBsign();
            //如果相同，则无需请求远程进行同步
            needSync = remoteUpdateSign.compareTo(dbUpdateSign) != 0;
            Log.i("StartDeal page=$page needSync=$needSync");
          }catch(e){
            Log.i("e=${e} page=$page");
            hasErr = true;
          }
        }
        //更新到本地
        if(!hasErr){
          TSysEntity sysEntity = TSysEntity();
          sysEntity.scode = AppConfig.T_SYS_UPDTAE_SIGN;
          sysEntity.svalue = remoteUpdateSign;
          await tSysProvider.insertOrUpdateBatch([sysEntity]);
        }
      }
      //上下架书籍
      Log.i("下架书籍id ${appConfig.down}");
      await batchUpdateBstatus(appConfig.down ?? [], AppConfig.BSTATUS_DOWN);
      //更新书籍border 排序顺序
      Log.i("开始更新书籍排序号====》");
      //远程
      Map<String?,int?>? remoteBorderMap = appConfig.border;
      Map<int,int> updateBorderMap = {};
      if(remoteBorderMap != null){
        //更新和远程不一致的id border
        remoteBorderMap.keys.forEach((remoteIdStr) {
          int remoteId = int.parse(remoteIdStr ?? "0");
          int remoteIdBorder = remoteBorderMap[remoteId] ?? -1;
          int dbIdBorder = dbBorderMap[remoteId ?? 0] ?? -1;
          if(dbBorderMap.containsKey(remoteId) && remoteIdBorder != dbIdBorder && remoteIdBorder > 0  ){
            updateBorderMap[remoteId ?? -1] = remoteIdBorder;
          }
        });
      }
      //更新 updateBorderMap 信息到本地数据库
      tBookProvider.updateBorderMap(updateBorderMap);
  }

  //批量书籍上下架状态
  static Future<int> batchUpdateBstatus(List<int> ids,int bstatus) async {
     if(ids.length == 0){
       return 0;
     }
     List<List<int>> pageIds =  DxmUtils.pageDatas(ids, AppConfig.DB_BATCH_SIZE);
     TBookProvider tBookProvider = Get.find();
     for(List<int> splitIds in pageIds){
       await tBookProvider.updateColValueById(tBookProvider.tableName(),splitIds, TBookProvider.column_bstatus, bstatus);
     }
     return ids.length;
   }

  //保存数据到本地db
  static saveLocalBookDatas(BookLocalPageVoEntity? result) async {
    if(result == null || result.datas == null){
      return;
    }
    //总数
    DateTime startTime = DateTime.now();
    TBookProvider tBookProvider = Get.find();
    List<TBookEntity> datas = result.datas ?? [];
    List<List<TBookEntity>> pageDatas = DxmUtils.pageDatas(datas, AppConfig.DB_BATCH_SIZE);
    for(var listDatas in pageDatas){
      try{
        await tBookProvider.insertOrUpdateBatch(listDatas);
      }catch(e){
        print(e);
      }
    }
    DateTime endTime = DateTime.now();
    int dur = endTime.difference(startTime).inMilliseconds;
    Log.i("Finished ${datas.length} in ${dur} ms ");
  }

  //分页查询列表，默认每页20条
  static Future<PageInfoVo<TBookEntity>> queryTBookPage(BookParams params) async{
    PageInfoVo<TBookEntity> result = PageInfoVo<TBookEntity>();
    result.page = params.page;
    result.pageSize = params.pageSize;
    TBookProvider tBookProvider = Get.find();
    result.data = await tBookProvider.queryList(params);
    result.count = await tBookProvider.countList(params);
    result.totalPage = result.calcTotalPage();
    //本地没有，从远程加载数据
    if((params.word  ?? "" ).isEmpty && (result.data ?? []).length == 0){
      result = await HttpCommmon.queryBookPageRemote(params.page ?? 1);
      int remoteSize = ( result.data ?? [] ).length;
      Log.i("本地数据库暂未初始化完整，从远程加载数据 remoteSize=${remoteSize}");
    }
    return result;
  }

  /**
   * 根据书籍id和书籍对应的phk,获取书籍基本信息+章节信息
   */
  static Future<TBookEntity> getBookChaptersRemote(int? bookid,String? phk) async{
    String api = AppConfig.bookBkifApi(bookid??0, phk ?? "");
    TBookEntity result = await HttpCommmon.getBookInfo(api);
    List<TBookContEntity> chapters = result.chapters ?? [];
    Log.i("远程获取bookid=${bookid} phk=${phk} 章节信息 chapters 数量=${chapters.length}");
    //将远程章节基本-信息更新到本地
    TBookContProvider contProvider = Get.find();
    Set<int> existChapterIds = await contProvider.getBookChapterIds(bookid ?? 0);
    List<TBookContEntity> addConts = [];
    int nowTmSec = (DateTime.now().millisecondsSinceEpoch/1000).toInt();
    for(TBookContEntity chapter in chapters){
      chapter.tmsec = nowTmSec;
      int chapterId = chapter.id ?? 0;
      if(existChapterIds.contains(chapterId)){
        //更新
        await contProvider.updateSelectiveById(chapter);
      }else{
        //插入
        addConts.add(chapter);
      }
    }
    addConts.forEach((element) {
      element.bookid = bookid;
    });
    //插入章节基本信息
    await contProvider.insertDatas(addConts);
    //t_book 更新 tmsec
    TBookProvider bookProvider = Get.find();
    TBookEntity bookUpPo = TBookEntity();
    bookUpPo.id = bookid;
    bookUpPo.tmsec = nowTmSec;
    await bookProvider.updateSelectiveById(bookUpPo);
    return result;
  }

  //根据章节id,和章节对应phk获取文本内容
  static Future<TBookContEntity> getChapterContRemote(int? bookContId,String? phk) async{
    String api = AppConfig.bookBkciApi(bookContId ?? 0, phk ?? "");
    //远程获取全部基本信息
    TBookContEntity result = await HttpCommmon.getBookContInfo(api);
    return result;
  }

  //获取书籍基本信息+章节基本信息
  static Future<List<TBookContEntity>> getChapters(TBookEntity bookInfo) async {
    TBookContProvider contProvider = Get.find();
    TBookProvider bookProvider = Get.find();
    //从本地db 获取 章节信息，
    BookContParams contParams = BookContParams();
    contParams.bookid = bookInfo.id;
    contParams.page = 1;
    contParams.pageSize = 1000000;
    List<TBookContEntity> chapters = await contProvider.queryBookContBaseInfo(contParams);
    //判断缓存时间
    int? chapterCacheTmsec = AppGlobCfg.CHAPTER_CACHE_TMSEC;
    TBookEntity? dbInfo = await bookProvider.getById(bookInfo.id ?? 0);
    int? bookTmsec = dbInfo != null ? dbInfo.tmsec : null;
    int nowTmSec = (DateTime.now().millisecondsSinceEpoch/1000).toInt();
    bool visitRemoteFlag = bookTmsec == null || (chapterCacheTmsec != null && nowTmSec - bookTmsec >= chapterCacheTmsec);
    Log.i("bookid=${bookInfo.id} bookTmSec=${bookTmsec} chapterCacheTmsec=${chapterCacheTmsec} visitRemoteFlag=${visitRemoteFlag}");
    if(chapters.length == 0 || visitRemoteFlag ){
      Log.i("bookid=${bookInfo.id} 远程加载章节信息===>");
      TBookEntity remoteBookResult = await getBookChaptersRemote(bookInfo.id, bookInfo.phk);
      chapters = remoteBookResult.chapters ?? [];
    }
    chapters.forEach((ele) {
      ele.bookid = bookInfo.id;
    });
    return chapters;
  }

}